﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Threading;
using DevEnverModal;
using QuailDashboard.View.Controls;
using QuailDashboard.View.Data;
using QuailDashboard.View.Helpers;
using QuailDashboard.View.Models;
using QuailDashboard.View.QuailServiceReference;

namespace QuailDashboard.View.Views
{
    /// <summary>
    /// The Home page for the quail dashboard - shows test results
    /// </summary>
    public partial class Home
    {
        private readonly HomePageState _state;
        private bool _infixcontrolsizes, _ishistorystale;
        private string _pendingSelectTestClass;
        private DispatcherTimer _filterTimer, _testlogTimer, _testlogHistoryTimer;
        private CheckBox _chkSelectAll;

        /// <summary>
        /// Initializes a new instance of the <see cref="Home"/> class.
        /// </summary>
        public Home()
        {
            InitializeComponent();
            _state = new HomePageState();
            _state.Modal = new ModalControl();
            _state.IncProcessing("Loading...");

            FilterDateTimeEnabled.IsChecked = true;
            _state.PropertyChanged += OnStateChanged;
            _state.FilterChanged += OnFilterChanged;
            _state.SelectedTestClassChanged += OnSelectedTestClassChanged;
            _state.SelectedTestChanged += OnSelectedTestChanged;
            _state.TestsLoaded += OnTestsLoaded;
            _state.HandleError += OnHandleError;
            _state.SelectedTestEnvironmentChanged += OnSelectedTestEnvironmentChanged;

            DataContext = _state;

            ResultGrid.AttachMouseScrolling();
            HistoryResultGrid.AttachMouseScrolling();
            NotesResultGrid.AttachMouseScrolling();

            ModalControl.ParentHost = LayoutRoot;

            _state.LoadEnvironment(App.CurrentApp.UserPreferences.Environment ?? "QAS");
        }

        /// <summary>
        /// Executes when the user navigates to this page.
        /// </summary>
        /// <param name="e">event arguments</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            _state.DecProcessing();
        }

        private void OnStateChanged(object sender, PropertyChangedEventArgs e)
        {
            var state = sender as HomePageState;
            if (state != null && state.IsLayoutLoaded)
            {
                if (e.PropertyName == "IsRefreshing" && !state.IsProcessing)
                    FixControlSizes();
            }
        }

        private void OnLayoutRootSizedChanged(object sender, SizeChangedEventArgs e)
        {
            FixControlSizes();
        }

        /// <summary>
        /// Attempts to resize the controls to keep them in the browser frame.  where the heck is the "Anchor" property?!!?
        /// </summary>
        private void FixControlSizes()
        {
            try
            {

                if (_infixcontrolsizes || !_contentLoaded)
                    return;

                _infixcontrolsizes = true;

                var pt0 = new Point(0, 0);

                // fix the height of the treeviewtests
                var gt = TreeViewTests.TransformToVisual(TestResultsGrid);
                var offset = gt.Transform(pt0);
                var h = RowTestResults.ActualHeight - offset.Y;

                if (h != TreeViewTests.Height)
                    TreeViewTests.Height = h;

                // fix the width of the ResultGrid
                gt = ResultGrid.TransformToVisual(ContentScrollViewer);
                offset = gt.Transform(pt0);

                var w = ContentScrollViewer.ViewportWidth - offset.X;

                if (w != ResultGrid.Width)
                    ResultGrid.Width = w;

                // fix the height of the ResultGrid
                gt = ResultGrid.TransformToVisual(TestResultsGrid);
                offset = gt.Transform(pt0);
                h = RowTestResults.ActualHeight - offset.Y;

                if (h != ResultGrid.Height)
                    ResultGrid.Height = h;

                // fix the height and width of the TestTabs
                gt = TestTabs.TransformToVisual(ContentScrollViewer);
                offset = gt.Transform(pt0);

                h = ContentScrollViewer.ViewportHeight - offset.Y;
                w = ContentScrollViewer.ViewportWidth - offset.X;

                if (w != TestTabs.Width)
                    TestTabs.Width = w;

                if (h != TestTabs.Height)
                    TestTabs.Height = h;

                _infixcontrolsizes = false;
            }
            catch
            {
                // eat resizing errors
            }
        }

        /// <summary>
        /// called when the layout changes - this code will select the _pendingSelectTestClass if it non-null
        /// </summary>
        /// <param name="sender">the treeview</param>
        /// <param name="e">unused arguments</param>
        private void TreeViewTests_LayoutUpdated(object sender, EventArgs e)
        {
            if (_pendingSelectTestClass != null)
            {
                var testclass = _pendingSelectTestClass;
                _pendingSelectTestClass = null;
                TreeViewTests.FindTreeViewItem(_state.TestClassHeirarchyList.FindTestClass(testclass));
            }
        }

        private void OnTestsLoaded(object sender, EventArgs e)
        {
            // _state.TestsLoaded -= OnTestsLoaded;
            _pendingSelectTestClass = App.CurrentApp.UserPreferences.SelectedTestClass;
        }

        private void OnSelectedTestChanged(object sender, RunStatusResultWrapper oldtest, RunStatusResultWrapper newtest)
        {
            RefreshTabData(true);
        }

        private void RefreshTabData(bool isstale)
        {
            if (isstale)
                _ishistorystale = true;

            if (TestTabs.SelectedItem == TabItemHistory)
                RefreshHistory();
            else if (TestTabs.SelectedItem == TabItemNoteHistory)
                RefreshNotes();
        }

        private void OnSelectedTestClassChanged(object sender, TestClassHeirarchy oldtest, TestClassHeirarchy newtest)
        {
            UpdateDataGrids();
        }

        private void OnFilterChanged(object sender, EventArgs e)
        {
            UpdateDataGrids();
        }

        private void UpdateDataGrids()
        {
            /* if (_chkSelectAll != null)
                _chkSelectAll.IsChecked = false; */
            if (!string.IsNullOrEmpty(_state.SelectedTestClassName))
                App.CurrentApp.UserPreferences.SelectedTestClass = _state.SelectedTestClassName;

            var existingpagedcollection = ResultGrid.ItemsSource as PagedCollectionView;

            if (existingpagedcollection == null)
            {
                var pagedcollection = new PagedCollectionView(_state.FilteredTestsForSelectedTestClass.ToList());

                pagedcollection.SortDescriptions.Add(new SortDescription("Data.RunStartDate", ListSortDirection.Descending));

                ResultGrid.ItemsSource = pagedcollection;
            }
            else
            {
                var tests = _state.FilteredTestsForSelectedTestClass.ToList();
                var hash = new Dictionary<int, RunStatusResultWrapper>();

                foreach (RunStatusResultWrapper existingtest in existingpagedcollection)
                {
                    hash.Add(existingtest.TestId, existingtest);
                }

                foreach (var test in tests)
                {
                    RunStatusResultWrapper existingtest;
                    if (hash.TryGetValue(test.TestId, out existingtest))
                    {
                        hash.Remove(test.TestId);
                        existingtest.SetEntireOriginalResult(test.OriginalResult);
                    }
                    else
                    {
                        existingtest = (RunStatusResultWrapper)existingpagedcollection.AddNew();
                        existingtest.SetEntireOriginalResult(test.OriginalResult);
                        existingpagedcollection.CommitNew();
                    }
                }

                if (hash.Count > 0)
                {
                    var removelist = new List<RunStatusResultWrapper>();
                    foreach (RunStatusResultWrapper existingtest in existingpagedcollection)
                    {
                        if (hash.ContainsKey(existingtest.TestId))
                        {
                            removelist.Add(existingtest);
                        }
                    }

                    foreach (var removetest in removelist)
                    {
                        existingpagedcollection.Remove(removetest);
                        existingpagedcollection.CommitEdit();
                    }
                }
            }

            RefreshTabData(false);
        }

        private void OnRefreshClick(object sender, RoutedEventArgs e)
        {
            _state.RefreshTests();
            TestRunLogs.RefreshData();
            RefreshTabData(true);            
        }

        private void FilterBox_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if (_filterTimer != null)
                    _filterTimer.Stop();

                PerformFilter();
            }
            else
            {
                if (_filterTimer == null)
                {
                    _filterTimer = new DispatcherTimer();
                    _filterTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
                    _filterTimer.Tick += OnFilterTick;
                }

                _filterTimer.Start();
            }
        }

        private void OnFilterTick(object sender, EventArgs e)
        {
            _filterTimer.Stop();
            PerformFilter();
        }

        private void PerformFilter()
        {
            _state.FilterString = FilterBox.Text;
        }

        private void TreeViewTests_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            _state.SelectedTestClass = TreeViewTests.SelectedItem as TestClassHeirarchy;
            _state.ActiveSelection = HomePageState.ActiveSelectionEnum.TestClass;
        }

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            _state.IsLayoutLoaded = true;
        }

        private void OnFilterDateTimeEnabled_Checked(object sender, RoutedEventArgs e)
        {
            FilterDateTime.IsEnabled = ((CheckBox)sender).IsChecked.Value;

            _state.FilterDate = FilterDateTime.IsEnabled ? FilterDateTime.DateTime : null;
        }

        private void FilterDateTime_DateTimeChanged(object sender, C1.Silverlight.DateTimeEditors.NullablePropertyChangedEventArgs<DateTime> e)
        {
            if (FilterDateTime.IsEnabled)
                _state.FilterDate = e.NewValue;
        }

        private void Filter_All(object sender, RoutedEventArgs e)
        {
            var checkbox = sender as CheckBox;
            var filterAll = false;
            if (checkbox != null)
                filterAll = checkbox.IsChecked.GetValueOrDefault();
            _state.FilterFailedYSOD = filterAll;
            _state.FilterFailed = filterAll;
            _state.FilterPassed = filterAll;
            _state.FilterWarning = filterAll;
            _state.FilterAsyncPending = filterAll;
            _state.FilterPending = filterAll;
            _state.FilterFailedTimeout = filterAll;
            _state.FilterFailedSync = filterAll;
            _state.FilterFailedQuail = filterAll;
            _state.FilterFailedThirdParty = filterAll;
        }

        private void Filter_Click(object sender, RoutedEventArgs e)
        {
            var b = sender as ToggleButton;

            if (b != null && b.Tag is string)
            {
                switch ((string)b.Tag)
                {
                    case "YSOD":
                        _state.FilterFailedYSOD = !_state.FilterFailedYSOD;
                        break;
                    case "Fail":
                        _state.FilterFailed = !_state.FilterFailed;
                        break;
                    case "Pass":
                        _state.FilterPassed = !_state.FilterPassed;
                        break;
                    case "Warning":
                        _state.FilterWarning = !_state.FilterWarning;
                        break;
                    case "AsyncPending":
                        _state.FilterAsyncPending = !_state.FilterAsyncPending;
                        break;
                    case "Pending":
                        _state.FilterPending = !_state.FilterPending;
                        break;
                    case "Timeout":
                        _state.FilterFailedTimeout = !_state.FilterFailedTimeout;
                        break;
                    case "Sync":
                        _state.FilterFailedSync = !_state.FilterFailedSync;
                        break;
                    case "Quail":
                        _state.FilterFailedQuail = !_state.FilterFailedQuail;
                        break;
                    case "ThirdParty":
                        _state.FilterFailedThirdParty = !_state.FilterFailedThirdParty;
                        break;
                }
            }
        }

        private void ResultGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var grid = (DataGrid) sender;
            if (grid.SelectedItem == null)
            {
                if (_testlogTimer != null)
                    _testlogTimer.Stop();
            }
            else
            {
                if (_testlogTimer == null)
                {
                    _testlogTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, 500) };
                    _testlogTimer.Tick += OnTestLogTick;
                }

                _testlogTimer.Start();
            }
        }

        private void OnTestLogTick(object sender, EventArgs e)
        {
            _testlogTimer.Stop();
            _state.SelectedTest = (RunStatusResultWrapper)ResultGrid.SelectedItem;

            if (FocusManager.GetFocusedElement() == ResultGrid)
                _state.ActiveSelection = HomePageState.ActiveSelectionEnum.Test;
        }

        private void TestTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                if (e.AddedItems.Contains(TabItemHistory))
                    RefreshHistory();

                if (e.AddedItems.Contains(TabItemNoteHistory))
                    RefreshNotes();
            }
        }

        private void RefreshNotes()
        {
            if (_state.SelectedTest == null)
                return;

            var existingpagedcollection = NotesResultGrid.ItemsSource as PagedCollectionView;

            _state.RefreshTestNotes(_state.SelectedTest);
            var pagedcollection = new PagedCollectionView(_state.SelectedTest.TestNotes);

            if (existingpagedcollection != null && existingpagedcollection.SortDescriptions.Count > 0)
            {
                foreach (var sd in existingpagedcollection.SortDescriptions)
                    pagedcollection.SortDescriptions.Add(sd);
            }
            else
            {
                pagedcollection.SortDescriptions.Add(new SortDescription("CreatedDate", ListSortDirection.Descending));
            }

            NotesResultGrid.ItemsSource = pagedcollection;
        }

        private void RefreshHistory()
        {
            if (!_ishistorystale)
                return;

            var existingpagedcollection = HistoryResultGrid.ItemsSource as PagedCollectionView;

            var pagedcollection = new PagedCollectionView(_state.GetHistoryTestsForSelectedTest());

            if (existingpagedcollection != null && existingpagedcollection.SortDescriptions.Count > 0)
            {
                foreach (var sd in existingpagedcollection.SortDescriptions)
                    pagedcollection.SortDescriptions.Add(sd);
            }
            else
            {
                pagedcollection.SortDescriptions.Add(new SortDescription("Data.RunStartDate", ListSortDirection.Descending));
            }

            HistoryResultGrid.ItemsSource = pagedcollection;
            _ishistorystale = false;
        }
 
        private void HistoryResultGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var grid = (DataGrid)sender;
            if (grid.SelectedItem == null)
            {
                if (_testlogHistoryTimer != null)
                    _testlogHistoryTimer.Stop();
            }
            else
            {
                if (_testlogHistoryTimer == null)
                {
                    _testlogHistoryTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, 500) };
                    _testlogHistoryTimer.Tick += OnHistoryTestLogTick;
                }

                _testlogHistoryTimer.Start();
            }
        }

        private void OnHistoryTestLogTick(object sender, EventArgs e)
        {
            _testlogHistoryTimer.Stop();
            _state.SelectedHistoryTest = (RunStatusResultWrapper)HistoryResultGrid.SelectedItem;
        }

        private void DeleteNote_Click(object sender, RoutedEventArgs e)
        {
            if (_state.SelectedTest != null && _state.SelectedTestNote != null)
            {
                _state.DeleteTestNote(_state.SelectedTest, _state.SelectedTestNote);
            }
        }

        private void AddNote_Click(object sender, RoutedEventArgs e)
        {
            if (_state.SelectedTest != null && _state.SelectedTest != null)
            {
                var ctrl = new TestNoteControl { Modal = _state.Modal };
                ctrl.Saved += OnSaveNote;
                ctrl.Test = _state.SelectedTest;
                ctrl.NewTestNote(_state.SelectedTest.TestId, _state.UserName);
                _state.Modal.ShowModal(ctrl);
            }
        }

        private void EditNote_Click(object sender, RoutedEventArgs e)
        {
            if (_state.SelectedTest != null && _state.SelectedTestNote != null)
            {
                var ctrl = new TestNoteControl { Modal = _state.Modal };
                ctrl.Saved += OnSaveNote;
                ctrl.Test = _state.SelectedTest;
                ctrl.TestNote = _state.SelectedTestNote;
                _state.Modal.ShowModal(ctrl);
            }
        }

        private void OnSaveNote(object sender, EventArgs e)
        {
            var ctrl = (TestNoteControl) sender;
            var note = ctrl.TestNote;

            if (note.TestNoteId == 0)
                _state.AddTestNote(ctrl.Test, note);
            else
                _state.SaveTestNote(ctrl.Test, note);
        }

        private void NotesResultGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _state.SelectedTestNote = (TestNote)NotesResultGrid.SelectedItem;
            var enablecontrols = _state.SelectedTestNote != null;

            EditNote.IsEnabled = enablecontrols;
            DeleteNote.IsEnabled = enablecontrols;
        }

        private void NotesResultGrid_SizeChanged(object sender, SizeChangedEventArgs e)
        {
        }

        private void NoteView_Click(object sender, RoutedEventArgs e)
        {
            TestTabs.SelectedItem = TabItemNoteHistory;
        }

        private void TakeOwnership_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(_state.UserName))
                return;

            var b = (Button) sender;
            var data = (RunStatusResultWrapper)b.DataContext;

            if (string.IsNullOrEmpty(data.TestOwner))
                _state.StartTakeOwnership(data);
            else
                _state.StartClearOwnership(data);
        }

        private static void OnHandleError(object sender, Exception e)
        {
            App.CurrentApp.ShowError(e);
        }

        /// <summary>
        /// Class used to bind to the Tab caption
        /// </summary>
        public class TabTextBinding : Model
        {
            private readonly string _text;
            private int _count;

            /// <summary>
            /// Initializes a new instance of the <see cref="TabTextBinding"/> class.
            /// </summary>
            /// <param name="text">The text value</param>
            /// <param name="view">The items view.</param>
            public TabTextBinding(string text, PagedCollectionView view)
            {
                _text = text;

                if (view != null)
                {
                    _count = view.ItemCount;
                    view.CollectionChanged += DataChanged;
                }
            }

            /// <summary>
            /// Gets the text for the tab
            /// </summary>
            public string Text
            {
                get
                {
                    return _text + " (" + _count + ")";
                }
            }

            private void DataChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                var newcount = ((PagedCollectionView)sender).ItemCount;

                if (newcount != _count)
                {
                    _count = newcount;
                    NotifyPropertyChanged("Text");
                }
            }
        }



        private void SelectTestCheckChanged(object sender, RoutedEventArgs e)
        {
            var chkSelected = (CheckBox) sender;
            foreach (var trd in _state.FilteredTests)
            {
                if (string.IsNullOrEmpty(trd.TestOwner) || (trd.TestOwner == _state.UserName))
                {
                    if (trd.IsChecked != (bool) chkSelected.IsChecked)
                    {
                        trd.IsChecked = (bool) chkSelected.IsChecked;
                    }
                }
            }
        }

        private static RunStatusResultWrapper TestResultForGridItem(object item)
        {
            if (item is FrameworkElement)
            {
                var gridRow = DataGridRow.GetRowContainingElement((FrameworkElement) item);
                if (gridRow != null)
                    return gridRow.DataContext as RunStatusResultWrapper;

            }

            return null;
        }
       
        private void TestRun_Checked(object sender, RoutedEventArgs e)
        {
            var lastChecked = (CheckBox)sender;
            var touchedtrd = TestResultForGridItem(sender);
            if (touchedtrd != null)
                touchedtrd.IsChecked = lastChecked.IsChecked.GetValueOrDefault();

            if ((_chkSelectAll != null) && ((bool)_chkSelectAll.IsChecked) != (bool)lastChecked.IsChecked)
            {
                Func<bool> checkedTestRunsExist = () => _state.FilteredTestsForSelectedTestClass.Any(trd => trd.IsChecked);
                Func<bool> unCheckedTestRunsExist = () => _state.FilteredTestsForSelectedTestClass.Any(trd => !trd.IsChecked);

                if (_chkSelectAll.IsChecked != (checkedTestRunsExist() && !unCheckedTestRunsExist()))
                {
                    _chkSelectAll.Checked -= SelectTestCheckChanged;
                    _chkSelectAll.Unchecked -= SelectTestCheckChanged;
                    _chkSelectAll.IsChecked = !_chkSelectAll.IsChecked;
                    _chkSelectAll.Checked += SelectTestCheckChanged;
                    _chkSelectAll.Unchecked += SelectTestCheckChanged;
                }
            }
        }

        private void chkSelectAll_Loaded(object sender, RoutedEventArgs e)
        {
            _chkSelectAll = sender as CheckBox;
        }

        private void btnExecuteTest_Click(object sender, RoutedEventArgs e)
        {
            // execute a single test
            var test = TestResultForGridItem(sender);
            if (test != null)
            {
                var list = new List<RunStatusResultWrapper> {test};
                _state.ExecuteTests(list, null);
            }
        }

        private void btnExecuteTestClass_Click(object sender, RoutedEventArgs e)
        {
            // execute a single test
            if (_state.SelectedTestClass != null)
            {
                var list = new List<TestClassHeirarchy> { _state.SelectedTestClass };
                _state.ExecuteTests(null, list);
            }
        }


        private void btnExecuteTests_Click(object sender, RoutedEventArgs e)
        {
            var testsToExecute = _state.FilteredTestsForSelectedTestClass.ToList();

            testsToExecute = testsToExecute
                .Where(trd => trd.IsChecked && !trd.IsExecuting)
                .ToList();

            if (testsToExecute.Count > 0)
            {
                _state.ExecuteTests(testsToExecute, null);
            }
            else
            {
                ChildWindow errorWin = new ErrorWindow("Please select a test", "Please check one or more tests to run.");
                errorWin.Show();
            }
        }

        private void ResultGrid_Loaded(object sender, RoutedEventArgs e)
        {
            var col = ResultGrid.Columns[0];
            if (!App.CurrentApp.EnableTestExecute)
                col.Visibility = Visibility.Collapsed;

            ResultGrid.MouseRightButtonDown += (thesender, mouseevent) => mouseevent.Handled = true;
            ResultGrid.MouseRightButtonUp += (thesender, mouseevent) =>
            {
                Point currentMousePosition = mouseevent.GetPosition(LayoutRoot);
                ShowPopup(currentMousePosition);
            };

            ResultGrid.KeyUp += (o, args) =>
                {
                    if (!_resultsGrid_IgnoreKeyboardEvents)
                    {
                        switch (args.Key)
                        {
                            case Key.Space:
                                ToggleSelectedTests();
                                break;
                            case Key.R:
                                if (Keyboard.Modifiers.HasFlag(ModifierKeys.Alt))
                                {
                                    RunSelectedTests();
                                }
                                break;
                        }
                    }
                };
        }

        private void Environment_Click(object sender, RoutedEventArgs e)
        {
            var ctrl = new SelectEnvironmentControl { Modal = _state.Modal };
            ctrl.Select += OnSelectEnvrionment;
            var selected = TestTabs.SelectedItem;
            if (selected == TabItemChart || selected == TabItemLoadTest || selected == TabItemHelp)
                TestTabs.SelectedItem = TabItemTestLogs;

            _state.Modal.ShowModal(ctrl);
        }

        private void OnSelectedTestEnvironmentChanged(object sender, TestEnvironment oldenv, TestEnvironment newenv)
        {
            if (newenv != null)
                App.CurrentApp.UserPreferences.Environment = newenv.EnvironmentName;

            _ishistorystale = true;
        }

        private void OnSelectEnvrionment(object sender, EventArgs e)
        {
            var ctrl = (SelectEnvironmentControl) sender;
            var env = ctrl.SelectedTestEnvironment;

            if (env != null)
                _state.SelectedTestEnvironment = env;
        }

        private void Chromify_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Browser.HtmlPage.Window.Navigate(new Uri("?WindowLess=false#/Home", UriKind.Relative));
            //http://localhost:88/Dashboard.aspx?WindowLess=false#/Home
        }

        #region Popup Stuff

        Popup popup = null;

        private void ShowPopup(Point currentMousePosition)
        {
            if (popup != null)
            {
                popup.IsOpen = false;
                popup = null;
            }
            popup = CreateContextMenu(currentMousePosition);
            popup.IsOpen = true;
        }

        private void HidePopup()
        {
            popup.IsOpen = false;
        }

        private Popup CreateContextMenu(Point currentMousePosition)
        {
            Popup popup = new Popup();
            Grid popupGrid = new Grid();
            Canvas popupCanvas = new Canvas();

            popup.Child = popupGrid;
            popupCanvas.MouseLeftButtonDown += (sender, e) => { HidePopup(); };
            popupCanvas.MouseRightButtonDown += (sender, e) => { e.Handled = true; HidePopup(); };
            popupCanvas.Background = new SolidColorBrush(Colors.Transparent);
            popupGrid.Children.Add(popupCanvas);
            popupGrid.Children.Add(CreateContextMenuItems(currentMousePosition));

            popupGrid.Width = Application.Current.Host.Content.ActualWidth;
            popupGrid.Height = Application.Current.Host.Content.ActualHeight;
            popupCanvas.Width = popupGrid.Width;
            popupCanvas.Height = popupGrid.Height;

            return popup;
        }

        private FrameworkElement CreateContextMenuItems(Point currentMousePosition)
        {
            string[] contextMenuItemsText = { "Run Checked", "Run Selected", "Check Selection", "Uncheck Selection", "Check All", "Uncheck All", "Copy" };

            ListBox lstContextMenu = new ListBox();
            foreach (string str in contextMenuItemsText)
            {
                TextBlock txb = new TextBlock() { Text = str };
                txb.MouseLeftButtonUp += new MouseButtonEventHandler(txb_MouseLeftButtonUp);
                lstContextMenu.Items.Add(txb);
            }

            Grid rootGrid = new Grid()
            {
                HorizontalAlignment = HorizontalAlignment.Left,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = new Thickness(currentMousePosition.X, currentMousePosition.Y, 0, 0)
            };
            rootGrid.Children.Add(lstContextMenu);

            return rootGrid;
        }

        protected void txb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            string menu = string.Empty;

            if (sender != null)
            {
                menu = (sender as TextBlock).Text;
                //txbMessage.Text = "You clicked on: " + menu;
            }

            switch (menu)
            {
                case "Run Checked":
                    btnExecuteTests_Click(this, new RoutedEventArgs());
                    break;
                case "Run Selected":
                    RunSelectedTests();
                    break;
                case "Check Selection":
                    CheckSelectedTests();
                    break;
                case "Uncheck Selection":
                    UnCheckSelectedTests();
                    break;
                case "Check All":
                    _chkSelectAll.IsChecked = true;
                    break;
                case "Uncheck All":
                    _chkSelectAll.IsChecked = true;
                    _chkSelectAll.IsChecked = false;
                    break;
                case "Copy":
                    CopyToClipboard();
                    break;
            }

            HidePopup();
        }

        public void CopyToClipboard()
        {
            try
            {
                var results = new StringBuilder();

                (from object item in ResultGrid.SelectedItems select item as RunStatusResultWrapper)
                    .ForEach(t => results.AppendLine(string.Format("({0}) {1}", t.OriginalResult.RunStatus, t.TestName)));

                Clipboard.SetText(results.ToString());
            }
            catch
            {
                // ignore exceptions fired when user cancels copy dialog
            }
        }

        public void ToggleSelectedTests()
        {
            var testsToSelect = (from object item in ResultGrid.SelectedItems select item as RunStatusResultWrapper).ToList();

            var test = testsToSelect.FirstOrDefault(t => t.IsExecuting == false);

            if (test != null)
            {
                if (test.IsChecked)
                {
                    UnCheckSelectedTests();
                }
                else
                {
                    CheckSelectedTests();
                }
            }

        }

        public void CheckSelectedTests()
        {
            var testsToSelect = (from object item in ResultGrid.SelectedItems select item as RunStatusResultWrapper).ToList();

            testsToSelect.Where(t => t.IsExecuting == false)
                .ForEach(t => t.IsChecked = true);
        }

        public void UnCheckSelectedTests()
        {
            var testsToSelect = (from object item in ResultGrid.SelectedItems select item as RunStatusResultWrapper).ToList();

            testsToSelect.Where(t => t.IsExecuting == false)
                .ForEach(t => t.IsChecked = false);
        }

        public void RunSelectedTests()
        {
            var testsToExecute = (from object item in ResultGrid.SelectedItems select item as RunStatusResultWrapper).ToList();

            testsToExecute = testsToExecute
                .Where(trd => !trd.IsExecuting)
                .ToList();

            if (testsToExecute.Count > 0)
            {
                _state.ExecuteTests(testsToExecute, null);
            }
            else
            {
                ChildWindow errorWin = new ErrorWindow("Please select a test", "Please check one or more tests to run.");
                errorWin.Show();
            }
        }

        #endregion

        private bool _resultsGrid_IgnoreKeyboardEvents = false;

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            // Prevent keyboard events from bubbling up to the grid
            _resultsGrid_IgnoreKeyboardEvents = true;

        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            // Turn on keyboard events so they bubble up now that we are done editing textbox
            _resultsGrid_IgnoreKeyboardEvents = false;
        }
    }
}